import cv2
import numpy as np
import mediapipe as mp


# 初始化 Mediapipe
mp_face_mesh = mp.solutions.face_mesh
mp_face_detection = mp.solutions.face_detection

# 加载目标脸
target_img = cv2.imread("face.png")
target_img = cv2.resize(target_img, (480, 640))  # 固定大小，方便演示

# 初始化摄像头
cap = cv2.VideoCapture(0)

def get_center(landmarks, ids, w, h):
    x = sum([landmarks[i].x for i in ids]) / len(ids)
    y = sum([landmarks[i].y for i in ids]) / len(ids)
    return int(x * w), int(y * h)

with mp_face_mesh.FaceMesh(static_image_mode=False, max_num_faces=1, refine_landmarks=True) as face_mesh:
    while True:
        ret, frame = cap.read()
        if not ret:
            break

        # 转换为 RGB
        rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        results = face_mesh.process(rgb)

        if results.multi_face_landmarks:
            for face_landmarks in results.multi_face_landmarks:
                h, w, _ = frame.shape

                # 取眼睛和嘴巴关键点（用于定位）
                #left_eye_ids = [33, 133, 159, 145]
                #right_eye_ids = [263, 362, 386, 374]

                left_eye = face_landmarks.landmark[33]   # 左眼
                right_eye = face_landmarks.landmark[263] # 右眼


                mouth = face_landmarks.landmark[13]      # 嘴巴
                # 转换成像素坐标
                pts = np.array([
                    (int(left_eye.x * w), int(left_eye.y * h)),
                    (int(right_eye.x * w), int(right_eye.y * h)),
                    (int(mouth.x * w), int(mouth.y * h))
                ], dtype=np.float32)

                # 目标脸上的对应点（左眼、右眼、嘴巴）
                target_pts = np.array([
                    (221, 389),  # 左眼
                    (423, 381), # 右眼
                    (325, 593)  # 嘴巴
                ], dtype=np.float32)

                # 仿射变换
                M = cv2.getAffineTransform(target_pts, pts)
                warped_face = cv2.warpAffine(target_img, M, (w, h))

                # 创建掩码
                gray = cv2.cvtColor(warped_face, cv2.COLOR_BGR2GRAY)
                _, mask = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)

                # 融合到原图
                #center = (w // 2, h // 2)
                landmark = face_landmarks.landmark[1] #1或33都可以，试一下
                cx, cy = int(landmark.x * w), int(landmark.y * h)
                center = (cx, cy)  # 人脸中心位置

                output = cv2.seamlessClone(warped_face, frame, mask, center, cv2.NORMAL_CLONE)

                cv2.imshow("Swap Result", output)
        else:
            cv2.imshow("Swap Result", frame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

cap.release()
cv2.destroyAllWindows()
